package com.novel.system.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.DruidStatManagerFacade;
import com.alibaba.druid.support.http.stat.WebAppStatManager;
import com.alibaba.druid.support.spring.stat.SpringStatManager;
import com.novel.framework.base.BaseController;
import com.novel.framework.result.Result;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * druid监控信息
 *
 * @author novel
 * @since 2022/4/19 21:03
 */
@RestController
@RequestMapping("/system/druidMonitor")
public class DruidStatController extends BaseController {
    /**
     * 基本信息
     *
     * @return 基本信息
     */
    @SaCheckPermission("monitor:basic:list")
    @GetMapping("/basic")
    public Result basic() {
        Map<String, Object> basicStat = DruidStatManagerFacade.getInstance().returnJSONBasicStat();
        return toAjax(basicStat);
    }

    /**
     * 重置所有
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:basic:resetAll")
    @PutMapping("/resetAll")
    public Result resetAll() {
        DruidStatManagerFacade.getInstance().resetAll();
        return success();
    }

    /**
     * 记录并重置
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:basic:logAndReset")
    @PutMapping("/logAndReset")
    public Result logAndReset() {
        DruidStatManagerFacade.getInstance().logAndResetDataSource();
        return success();
    }

    /**
     * 数据源
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:datasource:list")
    @GetMapping("/datasource")
    public Result datasource() {
        List<Map<String, Object>> statDataList = DruidStatManagerFacade.getInstance().getDataSourceStatDataList();
        return toAjax(statDataList);
    }

    /**
     * 激活的连接堆栈信息
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:datasource:list")
    @GetMapping("/activeConnectionStackTrace")
    public Result activeConnectionStackTrace() {
        List<List<String>> activeConnStackTraceList = DruidStatManagerFacade.getInstance().getActiveConnStackTraceList();
        return toAjax(activeConnStackTraceList);
    }

    /**
     * 数据源信息
     *
     * @param id id
     * @return 结果
     */
    @SaCheckPermission("monitor:datasource:list")
    @GetMapping("/datasource/{id}")
    public Result datasource(@PathVariable Integer id) {
        Map<String, Object> dataSourceStatData = DruidStatManagerFacade.getInstance().getDataSourceStatData(id);
        return toAjax(dataSourceStatData);
    }

    /**
     * 连接信息
     *
     * @param id id
     * @return 结果
     */
    @SaCheckPermission("monitor:datasource:list")
    @GetMapping("/connectionInfo/{id}")
    public Result connectionInfo(@PathVariable Integer id) {
        List<Map<String, Object>> connectionInfo = DruidStatManagerFacade.getInstance().getPoolingConnectionInfoByDataSourceId(id);
        return toAjax(connectionInfo);
    }

    /**
     * 激活的连接信息
     *
     * @param id id
     * @return 结果
     */
    @SaCheckPermission("monitor:datasource:list")
    @GetMapping("/activeConnectionStackTrace/{id}")
    public Result activeConnectionStackTrace(@PathVariable Integer id) {
        List<String> activeConnectionStackTrace = DruidStatManagerFacade.getInstance().getActiveConnectionStackTraceByDataSourceId(id);
        return toAjax(activeConnectionStackTrace);
    }

    /**
     * sql 信息
     *
     * @param dataSourceId 数据源id
     * @param orderBy      排序
     * @param orderType    排序类型
     * @param page         当前页
     * @param perPageCount 页大小
     * @return 结果
     */
    @SaCheckPermission("monitor:sql:list")
    @GetMapping("/sql")
    public Result sql(Integer dataSourceId, String orderBy, String orderType, Integer page, Integer perPageCount) {
        List<Map<String, Object>> sqlStatDataList = DruidStatManagerFacade.getInstance().getSqlStatDataList(dataSourceId);
        return toAjax(sqlStatDataList);
    }

    /**
     * sql详情
     *
     * @param id id
     * @return 结果
     */
    @SaCheckPermission("monitor:sql:list")
    @GetMapping("/sqlDetail/{id}")
    public Result sqlDetail(@PathVariable Integer id) {
        Map<String, Object> map = DruidStatManagerFacade.getInstance().getSqlStatData(id);
        if (map == null) {
            return success();
        }
        DbType dbType = DbType.of((String) map.get("DbType"));
        String sql = (String) map.get("SQL");

        map.put("formattedSql", SQLUtils.format(sql, dbType));
        List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);
        if (!statementList.isEmpty()) {
            SQLStatement sqlStmt = statementList.get(0);
            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
            sqlStmt.accept(visitor);
            map.put("parsedTable", visitor.getTables().toString());
            map.put("parsedFields", visitor.getColumns().toString());
            map.put("parsedConditions", visitor.getConditions().toString());
            map.put("parsedRelationships", visitor.getRelationships().toString());
            map.put("parsedOrderbycolumns", visitor.getOrderByColumns().toString());
        }
        return toAjax(map);
    }

    /**
     * sql 防火墙
     *
     * @param dataSourceId 数据源id
     * @param orderBy      排序
     * @param orderType    排序类型
     * @param page         当前页
     * @param perPageCount 页大小
     * @return 结果
     */
    @SaCheckPermission("monitor:wall:list")
    @GetMapping("/wall")
    public Result wall(Integer dataSourceId, String orderBy, String orderType, Integer page, Integer perPageCount) {
        Map<String, Object> wallStatMap = DruidStatManagerFacade.getInstance().getWallStatMap(dataSourceId);
        return toAjax(wallStatMap);
    }

    /**
     * 防火墙
     *
     * @param id id
     * @return 结果
     */
    @SaCheckPermission("monitor:wall:list")
    @GetMapping("/wall/{id}")
    public Result wall(@PathVariable Integer id) {
        Map<String, Object> wallStatMap = DruidStatManagerFacade.getInstance().getWallStatMap(id);
        return toAjax(wallStatMap);
    }

    /**
     * web监控
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:url:list")
    @GetMapping("/webUri")
    public Result webUri() {
        List<Map<String, Object>> uriStatData = WebAppStatManager.getInstance().getURIStatData();
        return toAjax(uriStatData);
    }

    /**
     * web监控
     *
     * @param url url地址
     * @return 结果
     */
    @SaCheckPermission("monitor:url:list")
    @GetMapping("/webUriByUrl")
    public Result webUri(String url) {
        Map<String, Object> uriStatData = WebAppStatManager.getInstance().getURIStatData(url);
        return toAjax(uriStatData);
    }

    /**
     * app  监控
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:web:list")
    @GetMapping("/webApp")
    public Result webApp() {
        List<Map<String, Object>> webAppStatData = WebAppStatManager.getInstance().getWebAppStatData();
        return toAjax(webAppStatData);
    }

    /**
     * spring监控
     *
     * @return 结果
     */
    @SaCheckPermission("monitor:spring:list")
    @GetMapping("/spring")
    public Result spring() {
        List<Map<String, Object>> methodStatData = SpringStatManager.getInstance().getMethodStatData();
        return toAjax(methodStatData);
    }

    /**
     * spring 详情
     *
     * @param className  类名
     * @param methodName 方法名
     * @return 结果
     */
    @SaCheckPermission("monitor:spring:list")
    @GetMapping("/springDetail")
    public Result springDetail(String className, String methodName) {
        Map<String, Object> methodStatData = SpringStatManager.getInstance().getMethodStatData(className, methodName);
        return toAjax(methodStatData);
    }

}